package com.xyy.saas.payment.common.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.xyy.saas.payment.adpater.yzh.util.HttpUtil;
import com.xyy.saas.payment.common.HolidayService;
import com.xyy.saas.payment.util.RedisUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @author wangzeqi
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class HolidayServiceImpl implements HolidayService {

    @Value("${queryHolidaysKey:43bc2e8003d8104d051b40213d8d34da1e88}")
    private String queryHolidaysKey;
    private final RedisUtil redisUtil;
    private final static DateTimeFormatter FORMATTER1 = DateTimeFormatter.ofPattern("yyyyMM");
    private final static DateTimeFormatter FORMATTER2 = DateTimeFormatter.ofPattern("yyyyMMdd");

    @Override
    public void refreshHolidayCache(LocalDate day) {
        try {
            if (!redisUtil.tryLock(RedisUtil.HOLIDAY_REFRESH_CACHE_LOCK)) {
                log.info("HolidayService refreshCache locking!");
                return;
            }
            // 月份和对应的非工作日日期，存上个月，当月，次月三个月的非工作日 格式为20240822
            Map<Integer, Set<Integer>> monthHolidaysyMap = new HashMap<>(3);
            int[] sub = new int[]{-1, 0, 1};
            for (int i = 0; i < 3; i++) {
                int yearMonth = Integer.parseInt(FORMATTER1.format(day.minusMonths(sub[i])));
                Set<Integer> holidays = queryHolidays(yearMonth);
                if (CollectionUtils.isNotEmpty(holidays)) {
                    monthHolidaysyMap.put(yearMonth, holidays);
                }
            }
            if (MapUtils.isNotEmpty(monthHolidaysyMap)) {
                redisUtil.set2(RedisUtil.HOLIDAY_CACHE_KEY, monthHolidaysyMap);
            }
        } finally {
            redisUtil.unLock(RedisUtil.HOLIDAY_REFRESH_CACHE_LOCK);
        }
    }

    @Override
    public boolean isHoliday(LocalDate localDate) {
        Set<Integer> holidays = getHolidaysOfMonth(localDate);
        return holidays.contains(Integer.parseInt(FORMATTER2.format(localDate)));
    }

    @Override
    public Set<Integer> getHolidaysOfMonth(LocalDate day) {
        int yearMonth = Integer.parseInt(FORMATTER1.format(day));
        String str = redisUtil.get(RedisUtil.HOLIDAY_CACHE_KEY);
        if (StringUtils.isBlank(str)) {
            refreshHolidayCache(day);
            str = redisUtil.get(RedisUtil.HOLIDAY_CACHE_KEY);
        }
        if (StringUtils.isBlank(str)) {
            return Collections.emptySet();
        }
        Map<Integer, Set<Integer>> monthNotworkDayMap = JSON.parseObject(str, new TypeReference<Map<Integer, Set<Integer>>>() {
        });
        return monthNotworkDayMap.getOrDefault(yearMonth, Collections.emptySet());
    }

    @Override
    public LocalDate getNearestPrevWorkday(final LocalDate date) {
        // 当月、上个月
        Set<Integer> holidays = new HashSet<>();
        holidays.addAll(getHolidaysOfMonth(date));
        holidays.addAll(getHolidaysOfMonth(date.minusMonths(1)));
        LocalDate nearestPrevWorkday = date.minusDays(1);
        while (holidays.contains(Integer.parseInt(FORMATTER2.format(nearestPrevWorkday)))) {
            nearestPrevWorkday = nearestPrevWorkday.minusDays(1);
        }
        return nearestPrevWorkday;
    }

    /**
     * 调用程序坞 开源请求当前月节假日信息
     */
    private Set<Integer> queryHolidays(int yearMonth) {
        String url = "https://api.apihubs.cn/holiday/get?month=" + yearMonth + "&page=1&size=31&workday=2";
        if (StringUtils.isNotBlank(queryHolidaysKey)) {
            url = url + "&api_key=" + queryHolidaysKey;
        }
        Map<String, Object> responseMap = HttpUtil.getByUrl(url);
        log.info("queryHolidays yearMonth:{} res:{}", yearMonth, JSON.toJSONString(responseMap));
        Object resultData = responseMap.get("data");
        JSONArray jsonArray = JSON.parseObject((String) resultData).getJSONObject("data").getJSONArray("list");
        if (jsonArray == null || jsonArray.isEmpty()) {
            return Collections.emptySet();
        }
        Set<Integer> set = new HashSet<>();
        int size = jsonArray.size();
        for (int i = 0; i < size; i++) {
            JSONObject dayObject = jsonArray.getJSONObject(i);
            // 格式如 20240930
            Integer date = dayObject.getInteger("date");

            // 只存非工作日
            if (dayObject.getInteger("workday").equals(2)) {
                set.add(date);
            }
        }
        return set;
    }

}
